home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 1 / Cream of the Crop 1.iso / PROGRAM / CBGRX100.ARJ / COLORS.C < prev    next >
Text File  |  1992-04-10  |  10KB  |  398 lines

  1. /** 
  2.  ** COLORS.C 
  3.  **
  4.  **  Copyright (C) 1992, Csaba Biegl
  5.  **    820 Stirrup Dr, Nashville, TN, 37221
  6.  **    csaba@vuse.vanderbilt.edu
  7.  **
  8.  **  This file is distributed under the terms listed in the document
  9.  **  "copying.cb", available from the author at the address above.
  10.  **  A copy of "copying.cb" should accompany this file; if not, a copy
  11.  **  should be available from where this file was obtained.  This file
  12.  **  may not be distributed without a verbatim copy of "copying.cb".
  13.  **  You should also have received a copy of the GNU General Public
  14.  **  License along with this program (it is in the file "copying");
  15.  **  if not, write to the Free Software Foundation, Inc., 675 Mass Ave,
  16.  **  Cambridge, MA 02139, USA.
  17.  **
  18.  **  This program is distributed in the hope that it will be useful,
  19.  **  but WITHOUT ANY WARRANTY; without even the implied warranty of
  20.  **  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  21.  **  GNU General Public License for more details.
  22.  **/
  23.  
  24. #include "grx.h"
  25. #include "libgrx.h"
  26. #include "interrup.h"
  27. #include "gmalloc.h"
  28.  
  29. #include <string.h>
  30. #include <stdlib.h>
  31.  
  32.  
  33. typedef struct {
  34.     unsigned int  n:6;
  35.     unsigned int  state:2;        /* 0=free, 1=shared, 2=writable */
  36.     unsigned char r;
  37.     unsigned char g;
  38.     unsigned char b;
  39. } color;
  40.  
  41. #define C_FREE        0        /* free color */
  42. #define C_SHARED    1        /* shared (by GrAllocColor) */
  43. #define C_WRITABLE    2        /* writable (by GrAllocCell) */
  44.  
  45. #define KEEPBITS(v,n)                        \
  46.     v = ((v += (0x80 >> n)) > 0xff) ?                \
  47.     (0xff ^ (0xff >> n)) :                    \
  48.     (v & (0xff ^ (0xff >> n)))
  49.  
  50.  
  51. static color *colortable = NULL;    /* color info table */
  52. static int maxused;            /* max used index in table */
  53. static int freecolors;            /* number of free colors */
  54. static int whitecolor;            /* index of white color */
  55. static int RGBmode;            /* set when in RGB mode */
  56. static int lastcolors = -1;        /* # of colors last initted to */
  57.  
  58. #define init_done()    (lastcolors == _GrNumColors)
  59.  
  60. static void setcolor(int c,int r,int g,int b)
  61. {
  62.     REGISTERS regs;
  63.  
  64.     switch(_GrAdapterType) {
  65.       case GR_EGA:
  66.         regs.r_ax = 0x1000;
  67.         regs.r_bx = c & 0x0f;
  68.         regs.r_bx |= ((r & 0x40) << 7) | ((r & 0x80) << 3);
  69.         regs.r_bx |= ((g & 0x40) << 6) | ((g & 0x80) << 2);
  70.         regs.r_bx |= ((b & 0x40) << 5) | ((b & 0x80) << 1);
  71.         int10(®s);
  72.         break;
  73.       case GR_VGA:
  74.         if(_GrNumColors == 16) {
  75.         regs.r_ax = 0x1000;
  76.         regs.r_bx = (c & 0x0f) | ((c & 0x0f) << 8);
  77.         int10(®s);
  78.         }
  79. #ifdef __GNUC__
  80.         asm volatile(
  81.         "cli                                \n"
  82.         "movl    %0,%%eax                   \n"
  83.         "movl    $0x3c8,%%edx               \n"
  84.         "outb    %%al,%%dx                  \n"
  85.         "inb     $0x80,%%al                 \n"
  86.         "incl    %%edx                      \n"
  87.         "movl    %1,%%eax                   \n"
  88.         "shrb    $2,%%al                    \n"
  89.         "outb    %%al,%%dx                  \n"
  90.         "inb     $0x80,%%al                 \n"
  91.         "movl    %2,%%eax                   \n"
  92.         "shrb    $2,%%al                    \n"
  93.         "outb    %%al,%%dx                  \n"
  94.         "inb     $0x80,%%al                 \n"
  95.         "movl    %3,%%eax                   \n"
  96.         "shrb    $2,%%al                    \n"
  97.         "outb    %%al,%%dx                  \n"
  98.         "sti                                \n"
  99.         : /* NOTHING */
  100.         : "g" (c), "g" (r), "g" (g), "g" (b)
  101.         : "ax", "dx"
  102.         );
  103. #elif defined(__TURBOC__)
  104.         disable();
  105.         outportb(0x3c8,c);
  106.         inportb(0x80);
  107.         outportb(0x3c9,(r >> 2));
  108.         inportb(0x80);
  109.         outportb(0x3c9,(g >> 2));
  110.         inportb(0x80);
  111.         outportb(0x3c9,(b >> 2));
  112.         enable();
  113. #else
  114.         regs.r_ax = 0x1010;
  115.         regs.r_bx = c & 0xff;
  116.         regs.r_dx = ((r & 0xfc) << 6);
  117.         regs.r_cx = ((g & 0xfc) << 6) | ((b & 0xfc) >> 2);
  118.         int10(®s);
  119. #endif
  120.         break;
  121.     }
  122.     colortable[c].r = r;
  123.     colortable[c].g = g;
  124.     colortable[c].b = b;
  125. }
  126.  
  127. static int initcolors(void)
  128. {
  129.     int whitevalue;
  130.  
  131.     if((_GrCurrentMode >= GR_320_200_graphics) && !init_done()) {
  132.        switch(_GrNumColors) {
  133. #if (GRXPLANES & 16)
  134.           case 32768:
  135. #endif
  136.           case 2:
  137.         whitecolor = _GrNumColors - 1;
  138.         freecolors = 0;
  139.         RGBmode = TRUE;
  140.         maxused = 0;
  141.         break;
  142.           case 256:
  143.           case 16:
  144.         whitecolor = 15;
  145.         whitevalue = (_GrAdapterType == GR_EGA) ? 0xc0 : 0xfc;
  146.         if((_GrNumColors > lastcolors) && (colortable != NULL)) {
  147.             _GrFree(colortable);
  148.             colortable = NULL;
  149.         }
  150.         if(colortable == NULL) {
  151.             colortable = _GrMalloc(sizeof(color) * _GrNumColors);
  152.             if(colortable == NULL) return(FALSE);
  153.         }
  154.         memset(colortable,0,(sizeof(color) * _GrNumColors));
  155.         colortable[0].state = C_SHARED;
  156.         setcolor(0,0,0,0);
  157.         colortable[whitecolor].state = C_SHARED;
  158.         setcolor(whitecolor,whitevalue,whitevalue,whitevalue);
  159.         freecolors = _GrNumColors - 2;
  160.         maxused = whitecolor + 1;
  161.         RGBmode = FALSE;
  162.         break;
  163.         }
  164.         lastcolors = _GrNumColors;
  165.     }
  166.     return(init_done() ? TRUE : FALSE);
  167. }
  168.  
  169. void GrResetColors(void)
  170. {
  171.     lastcolors = (lastcolors >= _GrNumColors) ? (_GrNumColors + 1) : (-1);
  172.     initcolors();
  173. }
  174.  
  175. void GrRefreshColors(void)
  176. {
  177.     color *c;
  178.     int n;
  179.  
  180.     if(lastcolors != _GrNumColors)
  181.         initcolors();
  182.     else for(n = 0,c = colortable; n < maxused; n++,c++)
  183.         if(c->state != C_FREE) setcolor(n,c->r,c->g,c->b);
  184. }
  185.  
  186. void GrSetRGBcolorMode(void)
  187. {
  188.     color *c;
  189.     int n;
  190.  
  191.     if((init_done() || initcolors()) && !RGBmode &&
  192.        (_GrAdapterType == GR_VGA) &&
  193.        (_GrNumColors == 256)) {
  194.         for(n = 0,c = colortable; n < 256; n++,c++) {
  195.         c->state = C_SHARED;
  196.         c->n = 1;
  197.         setcolor(n,(n & 0xe0),((n << 3) & 0xe0),((n << 6) & 0xc0));
  198.         }
  199.         freecolors = 0;
  200.         whitecolor = 255;
  201.         RGBmode = TRUE;
  202.         maxused = 256;
  203.     }
  204. }
  205.  
  206. int GrNumColors(void)
  207. {
  208.     return(_GrNumColors);
  209. }
  210.  
  211. int GrNumFreeColors(void)
  212. {
  213.     if(!init_done()) initcolors();
  214.     return(freecolors);
  215. }
  216.  
  217. int GrWhite(void)
  218. {
  219.     return((init_done() || initcolors()) ? whitecolor : GrNOCOLOR);
  220. }
  221.  
  222. int GrBlack(void)
  223. {
  224.     return((init_done() || initcolors()) ? 0 : GrNOCOLOR);
  225. }
  226.  
  227. int GrAllocColor(int r,int g,int b)
  228. {
  229.     color *c;
  230.     int err,minerr;
  231.     int n,free = (-1);
  232.  
  233.     if(!init_done() && !initcolors()) return(GrNOCOLOR);
  234.     if(RGBmode) switch(_GrNumColors) {
  235. #if (GRXPLANES & 16)
  236.       case 32768:
  237.         KEEPBITS(r,5);
  238.         KEEPBITS(g,5);
  239.         KEEPBITS(b,5);
  240.         return((r << 7) | (g << 2) | (b >> 3));
  241. #endif
  242.       case 256:
  243.         KEEPBITS(r,3);
  244.         KEEPBITS(g,3);
  245.         KEEPBITS(b,2);
  246.         return(r | (g >> 3) | (b >> 6));
  247.       case 2:
  248.         return(((r*30 + g*59 + b*11) >= 128*100) ? 1 : 0);
  249.       default:
  250.         return(GrNOCOLOR);
  251.     }
  252.     switch(_GrAdapterType) {
  253.       case GR_EGA:
  254.         KEEPBITS(r,2);
  255.         KEEPBITS(g,2);
  256.         KEEPBITS(b,2);
  257.         break;
  258.       case GR_VGA:
  259.         KEEPBITS(r,6);
  260.         KEEPBITS(g,6);
  261.         KEEPBITS(b,6);
  262.         break;
  263.       default:
  264.         return(GrNOCOLOR);
  265.     }
  266.     for(n = 0,c = colortable; n < maxused; n++,c++) {
  267.         switch(c->state) {
  268.           case C_SHARED:
  269.         if((c->r != r) || (c->g != g) || (c->b != b)) break;
  270.         c->n++;
  271.         return(n);
  272.           case C_FREE:
  273.         free = n;
  274.         break;
  275.         }
  276.     }
  277.     if((free < 0) && (maxused < _GrNumColors))
  278.         free = maxused++;
  279.     if(free >= 0) {
  280.         colortable[free].state = C_SHARED;
  281.         colortable[free].n = 1;
  282.         setcolor(free,r,g,b);
  283.         freecolors--;
  284.         return(free);
  285.     }
  286.     minerr = 3*32*32;
  287.     for(n = 0,c = colortable; n < _GrNumColors; n++,c++) {
  288.         if(c->state == C_SHARED) {
  289.         err = ((c->r - r) >> 2) * (c->r - r) +
  290.               ((c->g - g) >> 2) * (c->g - g) +
  291.               ((c->b - b) >> 2) * (c->b - b);
  292.         if(err <= minerr) {
  293.             minerr = err;
  294.             free = n;
  295.         }
  296.         }
  297.     }
  298.     if(free >= 0) {
  299.         colortable[free].n++;
  300.         return(free);
  301.     }
  302.     return(GrNOCOLOR);
  303. }
  304.  
  305. int GrAllocCell(void)
  306. {
  307.     int n,free = (-1);
  308.  
  309.     if((init_done() || initcolors()) && !RGBmode && (freecolors > 0)) {
  310.         for(n = 0; n < maxused; n++) {
  311.         if(colortable[n].state == C_FREE) {
  312.             free = n;
  313.             break;
  314.         }
  315.         }
  316.         if(free < 0) free = maxused++;
  317.         colortable[free].state = C_WRITABLE;
  318.         colortable[free].n = 1;
  319.         freecolors--;
  320.         return(free);
  321.     }
  322.     return(GrNOCOLOR);
  323. }
  324.  
  325. void GrFreeColor(int n)
  326. {
  327.     color *c;
  328.  
  329.     if(init_done() && !RGBmode &&
  330.        ((unsigned)n < (unsigned)_GrNumColors) &&
  331.        ((c = &colortable[n])->state != C_FREE)) {
  332.         if(c->n > 0)  c->n--;
  333.         if(c->n == 0) c->state = C_FREE;
  334.     }
  335. }
  336.  
  337. void GrSetColor(int n,int r,int g,int b)
  338. {
  339.     color *c;
  340.  
  341.     if((init_done() || initcolors()) && !RGBmode &&
  342.        ((unsigned)n < (unsigned)_GrNumColors)) {
  343.         c = &colortable[n];
  344.         switch(c->state) {
  345.           case C_SHARED:
  346.         if(c->n > 0) return;
  347.         break;
  348.           case C_FREE:
  349.         if(n >= maxused) maxused = n + 1;
  350.         freecolors--;
  351.         break;
  352.         }
  353.         c->state = C_WRITABLE;
  354.         c->n = 1;
  355.         switch(_GrAdapterType) {
  356.           case GR_EGA:
  357.         KEEPBITS(r,2);
  358.         KEEPBITS(g,2);
  359.         KEEPBITS(b,2);
  360.         break;
  361.           case GR_VGA:
  362.         KEEPBITS(r,6);
  363.         KEEPBITS(g,6);
  364.         KEEPBITS(b,6);
  365.         break;
  366.         }
  367.         setcolor(n,r,g,b);
  368.     }
  369. }
  370.  
  371. void GrQueryColor(int n,int *r,int *g,int *b)
  372. {
  373.     color *c;
  374.  
  375.     if(init_done() && ((unsigned)n < (unsigned)_GrNumColors)) {
  376.         if(colortable == NULL) switch(_GrNumColors) {
  377. #if (GRXPLANES & 16)
  378.           case 32768:
  379.         *r = (n >> 7) & 0xf8;
  380.         *g = (n >> 2) & 0xf8;
  381.         *b = (n << 3) & 0xf8;
  382.         return;
  383. #endif
  384.           case 2:
  385.         *r = *g = *b = (n ? 255 : 0);
  386.         return;
  387.           default:
  388.         *r = *g = *b = 0;
  389.         return;
  390.         }
  391.         c = &colortable[n];
  392.         *r = c->r;
  393.         *g = c->g;
  394.         *b = c->b;
  395.     }
  396. }
  397.  
  398.